
#include "mymainwindow.h"
#include "openglframe.h"
#include "typedefs.h"

#include <iostream>
#include <QtXml/QDomDocument>

using namespace std;

void printInfoAndExit() {
   
   cout<<endl;
   cout<<"Usage: qtSkelMeshAnim filename.{xml}"<<endl;
   exit(0);
}

/// Constructor.
MyMainWindow::MyMainWindow(QMainWindow *parent): QMainWindow(parent) {
   
   // Make sure the default opengl format includes stencil buffer and alpha.
   QGLFormat fmt;
   fmt.setAlpha(true);
   fmt.setStencil(true);
   QGLFormat::setDefaultFormat(fmt);
   
   // Executes the method which builds the remaining widgets of the window.
   // (Inherited from Ui::MainWindow)
   setupUi (this);
   
   timer = new QTimer(this);
   
   connect(actionZoomIn, SIGNAL(triggered()), this->glFrame, SLOT(zoomIn()));
   connect(actionZoomOut, SIGNAL(triggered()), this->glFrame, SLOT(zoomOut()));
   connect(actionZoomAll, SIGNAL(triggered()), this->glFrame, SLOT(zoomAll()));
   
   //~ connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(animateValueSlider(int)));
   connect(slider, SIGNAL(sliderPressed()), this, SLOT(setMaximumValueSlider()));
   connect(slider, SIGNAL(valueChanged(int)), this, SLOT(animateValueSlider(int)));
   
   //~ // groupping exclusives actions 
   meshrenderGroup = new QActionGroup(this);
   meshrenderGroup->addAction(actionRenderPoints);
   meshrenderGroup->addAction(actionRenderWireframe);
   meshrenderGroup->addAction(actionRenderHiddenLines);
   meshrenderGroup->addAction(actionRenderFlatLines);
   meshrenderGroup->addAction(actionRenderFlat);
   meshrenderGroup->addAction(actionRenderSmooth);
}

void MyMainWindow::open(int argc, char *argv[]) {
   
   if (argc < 2 or argc > 2) printInfoAndExit();
   
   QString filename(argv[1]);
   QFileInfo fi(filename);
   QString extension = fi.suffix();
   if (extension == "xml") 
      open_xmlfile(filename);
   else 
      printInfoAndExit();
}

void MyMainWindow::open_xmlfile(QString filename) {
   
   QFileInfo fi(filename);
   QString filepath = fi.absolutePath() + '/';
   //~ cout<<"fi.absolutePath() "<<fi.absolutePath().toStdString()<<endl;
   //~ cout<<"open_xmlfile>>>> "<<filename.toStdString().c_str()<<endl;
   /// ///////////////
   QDomDocument doc("AnimML");
   QFile file(filename);
   if (!file.open(QIODevice::ReadOnly))
      return;
   if (!doc.setContent(&file)) {
      file.close();
      return;
   }
   file.close();
   
   // print out the element names of all elements that are direct children
   // of the outermost element.
   QDomElement docElem = doc.documentElement();
   QDomNode dn = docElem.firstChild();
   while(!dn.isNull()) {
      QDomElement e = dn.toElement(); // try to convert the node to an element.
      if(!e.isNull()) {
         //~ cout << e.tagName().toStdString() << endl; // the node really is an element.
         //~ cout << e.attribute("meshfname").toStdString() << endl;
         //~ cout << e.attribute("skelfname").toStdString() << endl;
         //~ cout << e.attribute("skinfname").toStdString() << endl;
         //~ cout << e.attribute("motionfname").toStdString() << endl;
         
         if (not e.attribute("meshfname").isEmpty())
            glFrame->loadShape(filepath + e.attribute("meshfname")); 
         else { cout<<"Mesh file Input Error! "<<endl; exit(0); }
         if (not e.attribute("skelfname").isEmpty())
            glFrame->loadSkeleton(filepath + e.attribute("skelfname")); 
         else { cout<<"Skeleton file Input Error! "<<endl; exit(0); }
         if (not e.attribute("skinfname").isEmpty())
            glFrame->loadSkinning(filepath + e.attribute("skinfname")); 
         else { cout<<"Skinning(weights) file Input Error! "<<endl; exit(0); }
         if (not e.attribute("motionfname").isEmpty())
            if (not glFrame->loadMotion(filepath + e.attribute("motionfname"))) 
               {cout<<"Motion file Input Error! "<<endl; }
         
         QStringList tl = e.attribute("translation").split(" ", QString::SkipEmptyParts);
         if (tl.size() == 3) {
            float t[]={tl.at(0).toDouble(), tl.at(1).toDouble(), tl.at(2).toDouble()};
            glFrame->loadTranslation(t);
         }
         else {
            float t[]={0,0,0};
            glFrame->loadTranslation(t);
         }
      }
      dn = dn.nextSibling();
   }
   
   glFrame->buildAnimators();
}

void MyMainWindow::on_actionRenderPoints_triggered() {
   glFrame->meshRenderMode(POINTS);
   glFrame->updateGL();
}

void MyMainWindow::on_actionRenderWireframe_triggered() {
   glFrame->meshRenderMode(WIREFRAME);
   glFrame->updateGL();
}

void MyMainWindow::on_actionRenderFlat_triggered() {
   glFrame->meshRenderMode(FLAT);
   glFrame->updateGL();
}

void MyMainWindow::on_actionRenderFlatLines_triggered() {
   glFrame->meshRenderMode(FLATLINES);
   glFrame->updateGL();
}

void MyMainWindow::on_actionRenderHiddenLines_triggered() {
   glFrame->meshRenderMode(HIDDENLINES);
   glFrame->updateGL();
}

void MyMainWindow::on_actionRenderSmooth_triggered() {
   glFrame->meshRenderMode(SMOOTH);
   glFrame->updateGL();
}

void MyMainWindow::on_actionViewShadow_triggered() {
   
   if (actionViewShadow->isChecked())
      glFrame->viewItemOn(SHADOW);
   else 
      glFrame->viewItemOff(SHADOW);
   glFrame->updateGL();
}

void MyMainWindow::on_actionViewSkeleton_triggered() {
   
   if (actionViewSkeleton->isChecked())
      glFrame->viewItemOn(SKELETONDEF);
   else 
      glFrame->viewItemOff(SKELETONDEF);
   glFrame->updateGL();
}

void MyMainWindow::on_actionLightOnOff_triggered() {
   if (actionLightOnOff->isChecked())
      actionLightOnOff->setIcon(QIcon(QString::fromUtf8("icons/lighton.png")));
   else 
      actionLightOnOff->setIcon(QIcon(QString::fromUtf8("icons/lightoff.png")));
   glFrame->lightingOnOff(actionLightOnOff->isChecked());
   glFrame->updateGL();
}

void MyMainWindow::on_actionProjection_triggered() {
   
   if (glFrame->isProjectionOrtho()) {
      const QString qstring("Perspective");
      actionProjection->setText(qstring);
      actionProjection->setIcon(QIcon(QString::fromUtf8("icons/perspective.png")));
      glFrame->orthographic(false);
   }
   else {
      const QString qstring("Orthographic");
      actionProjection->setText(qstring);
      actionProjection->setIcon(QIcon(QString::fromUtf8("icons/orthographic.png")));
      glFrame->orthographic(true);
   }
   
   glFrame->setGLview();
   glFrame->updateGL();
}

void MyMainWindow::on_actionViewModel_triggered() {
   
   if (actionViewModel->isChecked())
      glFrame->viewItemOn(MODELDEF);
   else 
      glFrame->viewItemOff(MODELDEF);
   glFrame->updateGL();
}

void MyMainWindow::on_actionViewFloor_triggered() {
   
   if (actionViewFloor->isChecked())
      glFrame->viewItemOn(FLOOR);
   else 
      glFrame->viewItemOff(FLOOR);
   glFrame->updateGL();
}

void MyMainWindow::on_actionViewInfo_triggered() {
   
   if (actionViewInfo->isChecked())
      glFrame->viewItemOn(INFO);
   else 
      glFrame->viewItemOff(INFO);
   glFrame->updateGL();
}

void MyMainWindow::setMaximumValueSlider() {
   
   slider->setMaximum(glFrame->nMaxofFrames());
}

void MyMainWindow::animateValueSlider(int val) {
   
   glFrame->animateFrame(val-1);
}

void MyMainWindow::addValueSlider() {
   
   if (slider->value() < slider->maximum())
      slider->setValue(slider->value()+1);
   else
      on_bStop_clicked();
}

void MyMainWindow::on_bPlay_clicked() {
   
   slider->setMaximum(glFrame->nMaxofFrames());
   
   connect(timer, SIGNAL(timeout()), this, SLOT(addValueSlider()));
   timer->start(0);
}

void MyMainWindow::on_bStop_clicked() {
   
   slider->setValue(0);
   disconnect(timer, 0, 0, 0);
}

void MyMainWindow::on_bPause_clicked() {
   
   disconnect(timer, 0, 0, 0);
}

void MyMainWindow::on_bRecord_clicked() {
   
   if (bRecord->isChecked()) {
      connect(timer, SIGNAL(timeout()), this->glFrame, SLOT(record()));
      bRecord->setIcon(QIcon(QString::fromUtf8("icons/player_recording.png")));
      //timer->start(0);
   }
   else {
      // desconectarlo do timer, so ele
      bRecord->setIcon(QIcon(QString::fromUtf8("icons/player_recordstart.png")));
      disconnect(timer, 0, 0, 0);
   }
}
